package com.dcn.sign.controller;

import com.alibaba.fastjson.JSON;
import com.dcn.sign.model.*;
import com.dcn.sign.repository.*;
import com.dcn.sign.service.SignRecordService;
import com.dcn.sign.util.DataStrUtil;
import com.dcn.sign.vo.BgColor;
import com.dcn.sign.vo.DailyRecord;
import com.dcn.sign.vo.MonthRecord;
import com.zj.util.base.eo.DatePattern;
import com.zj.util.base.eo.Week;
import com.zj.util.utils.DateUtil;
import com.zj.util.utils.file.FileUtil;
import com.zj.util.utils.value.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author xi.yang(xi.yang@downjoy.com)
 * @create 2018-08-28 16:21
 **/
@Controller
public class SignRecordViewController {

    @Autowired
    private SignRecordRepository signRecordRepository;
    @Autowired
    private StaffRepository staffRepository;
    @Autowired
    private FileNameRepository fileNameRepository;
    @Autowired
    private SignRecordService signRecordService;
    @Autowired
    private HolidayRepository holidayRepository;
    @Autowired
    private SpDayTimeRepository spDayTimeRepository;

//    private static final String SIGN_RECORD_DIR = "/home/downjoy/dcn-sign/file/";
    private static final String SIGN_RECORD_DIR = "C:\\Users\\d.cn\\Desktop\\1111\\";
    private static final String START_TIME = "09:00";
    private static final String START_OVER_TIME = "09:30";
    private static final String END_TIME = "18:00";
    private static final String OVER_TIME = "21:00";
    private static final String OVER_END_TIME = "21:00";
    private static final Long WORK_DAY_HOURS = 9L;
    private static final Date startLimit = DateUtil.parseDate(START_TIME);
    private static final Date startOverLimit = DateUtil.parseDate(START_OVER_TIME);
    private static final Date endLimit = DateUtil.parseDate(END_TIME);
    private static final Date overLimit = DateUtil.parseDate(OVER_TIME);
    private static final Date overEndLimit = DateUtil.parseDate(OVER_END_TIME);

    public static final Logger logger = LoggerFactory.getLogger(SignRecordViewController.class);

    @RequestMapping("/refresh")
    public String refresh(Map<String, Object> map) {
        logger.warn("do get sign record");
        String[] fileNames = FileUtil.getFileNames(SIGN_RECORD_DIR);
        logger.warn(JSON.toJSONString(fileNames));
        if (null == fileNames) {
            return "ok";
        }
        List<String> files = new ArrayList<>();
        for (String fileName : fileNames) {
            FileName exist = fileNameRepository.findByFileName(fileName);
            if (exist != null) {
                continue;
            }
            exist = new FileName();
            exist.setFileName(fileName);
            exist.setCreateTime(new Date());
            fileNameRepository.save(exist);

            signRecordService.addSignRecords(SIGN_RECORD_DIR+fileName);

            files.add(fileName);
        }
        logger.warn(JSON.toJSONString(files));
        return "ok";
    }

    @RequestMapping(value = {"/", "/index"})
    public String findByStaffIdAndMonthState(HttpServletRequest request, Map<String, Object> map) {
//        获取所有的月份和当前月份
        List<String> months = DataStrUtil.getMonthStrs();
        String month = request.getParameter("month");
        if (StringUtil.isBlank(month)) {
            month = months.get(months.size() - 1);
        }
//        获取当前的用户
        String name = request.getParameter("staffId");
        if (StringUtil.isBlank(name)) {
            name = "阳熙";
        }
        Staff staff = staffRepository.findByName(name);
//        初始化前端日历布局数据，方便前端处理
        List<List<DailyRecord>> dailyReccordData = DataStrUtil.initDailyReccordData(month);
        Date start = DataStrUtil.getMonthStartDay(month);
        Date end = DataStrUtil.getMonthEndDay(month);
        List<SignRecord> signRecords = signRecordRepository.findByStaffAndDateStrBetween(staff, DateUtil.addDays(start, -1), DateUtil.addDays(end, 1));
        List<Holiday> holidays = holidayRepository.findAll();
        List<SpDayTime> spDayTimes = spDayTimeRepository.findAll();
        Map<Date, DailyRecord> dailyRecordMap = new HashMap<>();
        for (SignRecord signRecord : signRecords) {
            dailyRecordMap.put(signRecord.getDateStr(), covertDailyRecord(signRecord,holidays,getDateSpDayTime(spDayTimes,signRecord.getDateStr())));
        }

        for (List<DailyRecord> dailyReccordDatum : dailyReccordData) {
            for (DailyRecord dailyRecord : dailyReccordDatum) {
//                初始化颜色
                BgColor defColor = getDefaultColor(dailyRecord.getDate(), start, end, holidays);
                dailyRecord.setColor(defColor);

                if (dailyRecordMap.containsKey(dailyRecord.getDate())) {
                    DailyRecord data = dailyRecordMap.get(dailyRecord.getDate());
                    BeanUtils.copyProperties(data, dailyRecord);
                }
            }
        }
        List<Staff> staffs = staffRepository.findAll();
        MonthRecord monthRecord = getTotal(dailyRecordMap);
        DailyRecord firstData = getTimes(dailyReccordData);
        map.put("total", monthRecord);
        map.put("startDate", DateUtil.fmtDate(start,DatePattern.yyyyMMdd));
        map.put("endDate", DateUtil.fmtDate(end,DatePattern.yyyyMMdd));
        map.put("firstData", firstData);
        map.put("staff", staff);
        map.put("month", month);
        // record 返回格式： [日期,开始结束时间,是否全勤,加班时长,是否有餐补,打卡详情,背景色0-100]
        List<Object[]> records = new ArrayList<>();
        for (List<DailyRecord> dailyReccordDatum : dailyReccordData) {
            for (DailyRecord dailyRecord : dailyReccordDatum) {
                Object[] record = {
                        DateUtil.fmtDate(dailyRecord.getDate(), DatePattern.yyyyMMdd),
                        dailyRecord.getColor().getColorValue(),
                        dailyRecord.getTimeStr() == null ? "" : dailyRecord.getTimeStr(),
                        dailyRecord.isAllRight(),
                        dailyRecord.getOverHours(),
                        dailyRecord.isOverTime(),
                        dailyRecord.getTimes()
                };
                records.add(record);
            }
        }
        logger.warn("records===="+JSON.toJSONString(records));
        map.put("records", records);
        map.put("staffs", staffs);
        map.put("months", months);
        return "index";
    }

    private SpDayTime getDateSpDayTime(List<SpDayTime> spDayTimes, Date dateStr) {
        for (SpDayTime spDayTime : spDayTimes) {
            if (spDayTime.getDate().equals(dateStr)) {
                return spDayTime;
            }
        }
        return null;
    }

    private BgColor getDefaultColor(Date date, Date start, Date end, List<Holiday> holidays) {
        if (date.getTime() < start.getTime() || date.getTime() > end.getTime()) {
            return BgColor.darkgrayBg;
        }
        if (date.getTime() > System.currentTimeMillis()) {
            return BgColor.darkgrayBg;
        }
        if (isFreeTime(date, holidays)) {
            return BgColor.darkgrayBg;
        }
        return BgColor.redBg;
    }

    /**
     * 转换某天的数据
     * @param signRecord
     * @return
     */
    private DailyRecord covertDailyRecord(SignRecord signRecord,List<Holiday> holidays,SpDayTime spDayTime) {
        DailyRecord dailyRecord = new DailyRecord(signRecord.getDateStr());
        dailyRecord.setTimeStr(getTimeStr(signRecord));
//        打卡详情
        List<String> times = new ArrayList<>();
        for (Date time : signRecord.getTimes()) {
            times.add(DateUtil.fmtDate(time, DatePattern.HHmm));
        }
        dailyRecord.setTimes(times);
        boolean isFree = isFreeTime(signRecord.getDateStr(), holidays);
        final Date startTime = signRecord.getStartTime();
        final Date endTime = signRecord.getEndTime();
        if (isFree) {
            final long workHours = DateUtil.getHoursBetween(signRecord.getStartTime(), signRecord.getEndTime());
            if (workHours >= WORK_DAY_HOURS) {
                dailyRecord.setAllRight(true);
            }
            dailyRecord.setFreeTime(true);
            dailyRecord.setOverTime(true);
        }else {
            //  2018/8/29 正常时间
            final Date start = DateUtil.parseDate(DateUtil.fmtDate(startTime,DatePattern.HHmm));
            final Date end = DateUtil.parseDate(DateUtil.fmtDate(endTime, DatePattern.HHmm));
            //  判断是否算加班并计算加班时长
            if (end.getTime() >= overLimit.getTime()) {
                dailyRecord.setOverTime(true);
            }
            if (end.getTime() >= endLimit.getTime()) {
                //  2018/8/28 6:30开始算加班，所以要-1
                long halfHours = DateUtil.getHalfHoursBetween(endLimit, end)-1;
                if (halfHours > 0) {
                    dailyRecord.setOverHours(new BigDecimal(halfHours).divide(new BigDecimal(2)).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
                }
            }
            long startLimitTime = startLimit.getTime();
            long endLimitTime = endLimit.getTime();
            if (spDayTime != null) {
                startLimitTime = DateUtil.parseDate(DateUtil.fmtDate(spDayTime.getStart(),DatePattern.HHmm)).getTime();
                endLimitTime = DateUtil.parseDate(DateUtil.fmtDate(spDayTime.getEnd(),DatePattern.HHmm)).getTime();
            }
            boolean startRight = isStartRight(start, signRecord,startLimitTime);
            boolean endRight = isEndRight(end, signRecord,endLimitTime);
            if (startRight && endRight) {
                dailyRecord.setAllRight(true);
            }
        }
        if (dailyRecord.isAllRight()) {
            dailyRecord.setColor(BgColor.greenBg);
        }else {
            dailyRecord.setColor(BgColor.redBg);
        }
        return dailyRecord;
    }

    private boolean isEndRight(Date end, SignRecord signRecord,Long endLimitTime) {
//        正常打卡
        if (end.getTime() >= endLimitTime) {
            return true;
        }
        return false;
    }

    private boolean isStartRight(Date start, SignRecord signRecord,Long startLimitTime) {
//        正常打卡
        if (start.getTime() <= startLimitTime) {
            return true;
        }
//        迟到半小时，判断是否是前一天加班
//        if (start.getTime() <= startOverLimit.getTime()) {
//            SignRecord perDateSign = signRecordRepository.getByStaffAndDateStr(signRecord.getStaff(), DateUtil.addDays(signRecord.getDateStr(), -1));
//            if (null != perDateSign && DateUtil.parseDate(DateUtil.fmtDate(perDateSign.getEndTime(),DatePattern.HHmm)).getTime() >= overEndLimit.getTime()) {
//                return true;
//            }
//        }
        return false;
    }

    private boolean isFreeTime(Date date, List<Holiday> holidays) {
//        要先判断是否是节假日
        for (Holiday holiday : holidays) {
            if (holiday.getDate().equals(date)) {
                return holiday.getFree();
            }
        }
        final Week week = DateUtil.getWeek(date);
        if (Week.SATURDAY.equals(week) || Week.SUNDAY.equals(week)) {
            return true;
        }
        return false;
    }



    private MonthRecord getTotal(Map<Date, DailyRecord> map) {
        MonthRecord total = new MonthRecord();
        int freeDays = 0;
        int overTimes = 0;
        BigDecimal overHours = new BigDecimal(0);
        for (DailyRecord dailyRecord : map.values()) {
            if (dailyRecord.isFreeTime()) {
                freeDays++;
            }
            if (dailyRecord.isOverTime()) {
                overTimes++;
            }
            overHours = overHours.add(new BigDecimal(dailyRecord.getOverHours()));
        }
        total.setFreeDays(freeDays);
        total.setOverTimes(overTimes);
        total.setOverHours(overHours.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
        return total;
    }

    private DailyRecord getTimes(List<List<DailyRecord>> records) {
        for (List<DailyRecord> record : records) {
            for (DailyRecord dailyRecord : record) {
                if (dailyRecord.getTimes() != null) {
                    return dailyRecord;
                }
            }
        }
        return new DailyRecord(new Date());
    }


    private String getTimeStr(SignRecord signRecord) {
        if (signRecord.getStartTime() == null) {
            return "";
        }
        if (signRecord.getStartTime().equals(signRecord.getEndTime())) {
            return DateUtil.fmtDate(signRecord.getStartTime(), DatePattern.HHmm);
        }
        return DateUtil.fmtDate(signRecord.getStartTime(), DatePattern.HHmm) + "--" + DateUtil.fmtDate(signRecord.getEndTime(), DatePattern.HHmm);
    }

}
